Segue uma solução:
library(data.table)
funID <- function(x) nrow(unique(x))
dt.dados <- data.table(dados)
dt.dados[, list(N = funID(.SD)), by = list(ID, CONTRATO)][N > 1]
Eu ia dar a sugestão de usar um split + lapply + do.call, mas poderia ser problemático se houvesse um número grande de combinações ID x CONTRATO.
att,
Rubem