OK, I now know why it's not being formatted client-side, it's because esri.substitute does recognise it as something that might be parsed as a number and since the date-formatting code is within the 'number' branch it never makes it to the DateFormat nor DateString formatters 😞
I think that could be rectified client-side i.e. a better attempt to be made to determine whether the value might be a date or not...perhaps I'm missing the point but the field type being esriFieldTypeDate does provide a bit of a hint, does it not?!
Why the two server-side methods return different formats for the same field remains a mystery, perhaps someone from ESRI could explain as this seems to be the crux of the problem?