Sounds like an ideal scenario for an indexed view, which allows you to pay for calculations and aggregates at write time instead of query time.
CREATE VIEW dbo.MyIndexedView
SELECT Enroll_Date, UserID, RawCount = COUNT_BIG(*)
GROUP BY Enroll_Date, UserID;
CREATE UNIQUE CLUSTERED INDEX CIX_miv ON dbo.MyIndexedView(Enroll_Date, UserID);
That will take some time to create, and of course will require maintenance throughout all DML operations, just like an index on the base table.
Now the query against this view would be quite similar - each row in the view now represents a distinct user/date combo, so that figure can be calculated by a single COUNT(*), while the total number of rows in the base table is already partially aggregated for you, now you just need to add them up using SUM per date:
[Record #] = SUM(RawCount),
[User #] = COUNT(*)
FROM dbo.MyIndexedView WITH (NOEXPAND)
GROUP BY Enroll_Date;
Added NOEXPAND hint, after remembering this and this.
I can tell you without a doubt that this query will be faster than your current query (but not by how much), except in the rare case where you have exactly one user for each date (in which case the same amount of data will have to be read) and the columns we know about are the only columns in the base table's index. Whether that performance boost at read time is worth the extra work that will affect the write portion of your workload is something we can't tell you - you'll have to test it to measure the trade-off (no index is free).
And if you frequently use the same common WHERE clauses against Enroll_Date for specific, well-defined ranges (say, the current quarter or year to date), you could add matching filtered indexes that reduce that I/O even further (but there's always a trade-off).
You might also consider putting a clustered index on the base table. This doesn't seem to be one of those very rare use cases that benefit from a heap.