A quick guide on is_null and empty can be found here, I used to reference it quite a bit.
As you noted, is_null is a complainer. The only way to test this without throwing a NOTICE is to check if the variable is set in the global vars array. You can do this by testing as such:
// Is Set (to anything)
if(!(isset($var) || array_key_exists('var',get_defined_vars()))){ /* ... */ }
// Set and Null
if(!(is_null($var) || array_key_exists('var',get_defined_vars())))) { /* ... */ }
// Etc
The problem here is that you are using get_defined_vars and this has significant performance impacts, both in wall-time and memory usage, if over-used, and I would suggest it should just be used for debugging.
If you are interested in strictly global variables, you can use the $GLOBALS supervar. However, this will not give you access to variables inside the scope of a function or method: https://stackoverflow.com/a/418162/1301994
If you are trying to avoid NOTICES to increase performance, this is not worth it, as the overhead for check is greater than the slight performance gains.
I guess it really matters what your goals are. If you are working in an OOP fashion, then you should be able to tell fairly clearly if a variable is set or not in the scope of the method. Otherwise, it would be best to not code in such a way that undefined and NULL behave differently. If this is not possible, consider utilizing other flags to help you get around the use of get_undefined_vars.
Check below for a little more on the topic:
Is var set to null same as undefined and how to check differences