A function which has the same result in case of an error as when given valid input (hint: 'null' is a valid json string) is neither good design, nor something I would actually 'prefer'.
Aside of that (and more to the point of the original article), I do believe that exceptions can be very useful the deeper the abstraction of your libraries gets.
If you are 'far down' the stack and you want to ensure that you are in a position where it's safe to proceed and making it very, very clear for the caller that something went wrong, trow() is the perfect tool in order not to be called with a garbage argument on a successive call to a different function (hint: error results tend to get ignored).
And if you are a user of a library, getting nice exceptions can be very handy too - sometimes even wrapping and re- throwing them.
A very good example of real code: In a command line script which processes a lot of text-data to import into a database delegates to various importer classes depending on import line type.
All these importer classes do their thing and whenever they come across an issue, they just throw an ImporterException with all the context that they know about.
The parent script only has to deal with one single case of Exception to produce nice error messages and show everything about the context where they happened.
I can make the importers as complicated as they need to be and I never have to check a single return value (or forget to check it). There is one central place to handle whatever kind of Error that can creep up.
This is very handy.
Granted, in JS/node where each callback cleans out the stack so that a thrown exception can't be handled by whatever caused the callback to be executed later), exceptions are useless and actually harmful because they can mess up the program flow (which assumes callback to be triggered eventually).
But exceptions being useless in one environment doesn't make the useless everywhere.