This is really well-written. I was skeptical about the title's claim but truly, the author defines what first-class citizens mean and a wide range of cases where the behavior is inconsistent.
I have gotten used to its behavior but only because I use factors sparingly, having set stringsAsFactors=FALSE as my default. But reshape2::melt() requires a separate argument (factorsAsStrings) if you don't want automatic conversion, and with plyr::ldply() you can't prevent the index column conversion to a factor at all. So factors creep in periodically into my data frames and burns me every now and then.