I had the exact same issue and I stumbled on this question during my researches.
Unsatisfied by the general consensus, I created an extended Nullable struct, which I called Settable<T> for lack of imagination. Basically it is a nullable with an additional field, IsSet, which is true no matter which value you stored, as long as you stored something, and false only for default(Settable<T>), which is aliased as Settable<T>.Undefined.
A deserializer is going to write the Settable<T> only if he finds a corresponding property, in which case IsSet will be true. If the property is not included in the deserialized json, the default will be retained, which has IsSet == false. So, replacing your int? properties in your DTO type with a Settable is going to give you the required difference between undefined (or, more exactly, unspecified) and null.
Yay!
I uploaded the implementation into a repository on Github, for everyone to use (no warranty, use at your own risk, etc... I'm in hospital with 6 broken ribs and under painkillers: if something doesn't work it's YOUR fault):
https://github.com/alberto-chiesa/SettableJsonProperties
Edit: As for the comment about undefined serializing to null, I added a custom ContractResolver to handle Settable properties and updated the repository.